home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-08-14 | 14.3 KB | 291 lines | [TEXT/CWIE] |
- Writing Sneak3view Tests
- ======= ========== =====
-
-
- 3/29/96
-
-
-
-
-
- Introduction
- ============
-
- This document explains how to create your own tests for Sneak3view. The
- application itself, which is described in "Sneak3view Documentation,"
- comes with a number of built-in tests. These should be sufficient to begin
- debugging your drawing engine. Eventually, however, you will want to
- devise your own tests to debug a particular feature of your drawing engine.
-
- The process of writing Sneak3view tests is essentially as follows: write
- some C code to draw something to the screen. You will probably want to
- mirror the RAVE drawing calls to both draw contexts. There are libraries
- of functions included with Sneak3view which simplify that task. Then add
- some code to S3TestRegister.c to register your new test so that it will
- show up in Sneak3view's test menu. Finally, recompile Sneak3view and run
- your test. Repeat as necessary.
-
-
- Writing Tests
- ======= =====
-
- Although Sneak3view is written in C++ using PowerPlant, the tests
- themselves are written in plain C. Unless you want to customize a part
- of Sneak3view's interface, there should be no need to delve into the
- PowerPlant code.
-
- The files you will need to access in order to write your own tests are
- mostly in just two folders, Interfaces and Tests. Interfaces contains the
- header files which the test code can include. The headers used by the rest
- of Sneak3view are in the Headers folder and won't be of much use in
- writing tests.
-
- The Tests folder contains the test code itself. In the Sneak3view
- distribution there are several files in this folder. Of these, only
- S3TestRegister.c is required. You do not need to compile the tests in the
- other files into the application, but they are useful examples of how to
- write tests. Some of the tests in S3MoreTests.c use hard-coded file names,
- so they may or may not work if you try to run them.
-
-
- A Basic Example
- = ===== =======
-
- As a simple example of a Sneak3view test, take a look at S3TestTriGouraud,
- in S3RandomTests.c. The function draws (by default) 100 gouraud-shaded
- triangles in both draw contexts simultaneously.
-
- First notice that every test has a single parameter of type S3tTestInfo*.
- S3tTestInfo is an opaque data type which contains all the values which are
- controlled from the settings window in Sneak3view. Its fields are
- accessed through the functions in S3TestInfo.h. The return type of every
- test is S3tTestStatus, which is an enumeration of possible test results:
- failure, success, etc. If the test returns kS3Status_Failure, an alert to
- that effect is displayed to the user, so it's important to return the
- appropriate value at the end of a test.
-
- Only a few lines of code are required in S3TestTriGouraud to draw the
- triangles. First S3TestInfo_GetArgString is called to get a pointer to the
- string of arguments (if any) the user passed to the test. The argument
- string is scanned to find an unsigned integer. If one is found, it becomes
- the number of triangles that this test will draw. Otherwise, it will draw
- 100 triangles.
-
- S3Test_RenderStart is then called to begin rendering. S3TestSystem.h
- contains the prototypes of functions like S3Test_RenderStart which mirror
- RAVE calls to both draw contexts. Each of the routines in S3TestSystem.h
- take an S3tTestInfo pointer and possibly one or more other parameters. In
- the case of S3Test_RenderStart, the function first calls QARenderStart on
- the left draw context and then on the right.
-
- Inside the for-loop, S3TestUtil_DrawRandomTriGouraud is called. This
- utility function is prototyped in S3TestUtil.h. It simply draws a
- gouraud-shaded triangle made up of three randomly-placed and -colored
- verticies. To create the verticies it calls S3Testutil_RandomVGouraud.
- Drawing the resulting triangle to both contexts is accomplished through
- S3Test_DrawTriGouraud.
-
- Every 20 triangles, S3Test_Flush is called to force the engines to draw the
- triangles they have accumulated. After the flush, the function calls
- S3TestInfo_CheckForCancel. This routine scans the event queue for a
- command-period event. If it finds one it returns true. This lests the
- user cancel potentially lengthy operations. Note that if you are trying to
- time your engine's peak drawing speed, you probably don't want to call
- S3TestInfo_CheckForCancel inside an inner loop.
-
- At the end of the loop, S3Test_RenderEnd is called to finish the rendering
- process. Finally, status is returned to indicate whether the test was
- successfully completed or was instead cancelled.
-
-
- A More Interesting Example
- = ==== =========== =======
-
- S3ShowAllMipMaps is a rather more complex test. For one thing, it
- retrieves the texture's and the window's height and width from the
- S3tTestInfo, using functions like S3TestInfo_GetTextureWidth. It then
- makes sure that the window is large enough to contain the triangles the
- test is about to draw. If the window is too small, the test puts up an
- alert to that effect, letting the user know how big the window must be for
- the test to continue.
-
- S3StopAlert, prototyped in S3Alert.h, is a function which simply displays a
- stop alert box. You can pass it either a STR# resource ID and index or a
- Pascal string. S3ShowAllMipMaps builds up the string at runtime. Since
- the only resource fork open at runtime is Sneak3view's, it is generally
- best to use a Pascal string constant for your alert messages.
-
- The function also ensures that the Create Mipmap option has been checked in
- the settings window. It calls S3TestInfo_GetTextureFlags to retrieve the
- bitmask that Sneak3view passed to QATextureNew when it created the texture.
- If the Create Mipmap option has not been selected, another stop alert is
- displayed.
-
- Finally, S3ShowAllMipMaps draws the texture at each of its mipmapped
- sizes. The texture is rendered onto a square which is made up of two
- triangles using S3Test_DrawTriTexture.
-
-
- Timing Drawing Operations
- ====== ======= ==========
-
- Most RAVE calls are non-blocking: they return as soon as the geometry, e.g.
- a triangle, has been passed to the engine, but before the engine has drawn
- the triangle. Thus to get accurate timing information you can't simply
- measure the time between a call to QARenderStart and QARenderEnd. Instead,
- you must use QASync, which is a RAVE call that blocks until all the
- rendering in a particular context has finished. So to time the rendering
- of a scene, you could call S3MicrosecondCount (from S3Utilities.h) just
- before S3Test_RenderStart and S3ElapsedMicroseconds just after S3Test_Sync.
-
- However, you probably want the time each engine takes to draw its own
- scene, not the total time taken by both engines. To do this, you must draw
- first in one context and then in the other, using the RAVE calls directly
- (i.e., QADrawTriGouraud() instead of S3Test_DrawTriGouraud). This is the
- approach S3DrawGouraudTris takes, as shown in S3TimingTests.c. The
- resulting timing information is printed to the settings window's output
- view.
-
-
- Using More Than One Texture
- ===== ==== ==== === =======
-
- Although the Sneak3view settings window lets you select only one texture
- for use in a test, it is possible to load textures from files directly in
- your test code. The game test, in S3GameTest.c, loads 8 textures and 2
- bitmaps.
-
- Rather than hard-coding pathnames to the texture files, it is easier to
- use S3GetNearbyPICT. In this case, a "nearby" PICT is one whose name
- appears in the Texture and Bitmap popup menus in the settings window.
- Given the name of a file, S3GetNearbyPICT returns a PICT handle. If it
- can find no files with that name, it returns nil.
-
- Another way to get a texture is to ask the user for one, with
- S3GetPICTFileSpec. This routine displays the standard get-file dialog and
- lists only PICT files. With a valid FSSpec, you can then get a PICT handle
- from S3GetPICTFromFile.
-
- Once you have the PicHandle, you can create a new S3Image using
- S3Image_New. The header S3Image.h contains a C interface to a C++ class
- which handles the storage, mipmapping, etc. of textures and bitmaps. When
- you create a new S3Image, you must specify whether you want the image to be
- mipmapped and whether all the black pixels should be made transparent. You
- can either hardcode these flags or else read them from the S3tTestInfo
- struct, using routines like S3TestInfo_GetTextureMakeBlackTransparent. If
- you do the latter, the user can control whether black should be transparent
- by checking or unchecking that option in the settings window.
-
- To create a new texture, you must pass a TQAImage pointer to QATextureNew.
- You can access the TQAImage data in an S3Image by calling
- S3Image_GetImages. Once you are finished with the image data, after
- calling either QATextureDelete or QATextureDetach (which forces the engine
- to copy the pixmap into its own memory), you must call S3Image_Delete to
- dispose of the off-screen GWorld in which the PICT is stored.
-
-
- Calling One Test From Another
- ======= === ==== ==== =======
-
- One particularly useful feature of Sneak3view is the ability to run a test
- from within another. As long as the obvious dangers of infinite recursion
- are avoided, this can be extremely useful for regression-testing your
- drawing engine. By stringing together a number of small tests inside a
- larger one, you can verify your engine's functionality by running a single
- composite test.
-
- An example of this is found in S3GameTest.c. The composite test
- S3GameSceneEveryFormat() runs "Game Scene" over and over, each time
- changing the texture and bitmap formats. In this way you can check that
- each of the RAVE formats works with your engine in a complex scene.
-
- The test first sets a number of fields in the S3tTestInfo structure. Since
- S3tTestInfo is an opaque data type, you must set the fields through a
- tag-based mechanism, similar to the method used for changing RAVE state
- variables. For example, the black areas of the bitmaps are forced to be
- transparent with this call:
-
- s3Error = S3TestInfo_SetLong(inTestInfo,
- kS3TagLong_BitmapMakeBlackTransparent, true);
-
- The tags for each of the fields that can be set are listed in S3TestInfo.h.
-
- After the initial setup, the test loops through each of the possible
- texture and bitmap formats. S3TestInfo_SetLong() is used to set the
- formats. S3TestInfo_RunTest() takes a string and runs the test with that
- name.
-
- When the test has returned, S3GameSceneEveryFormat() calls
- S3TestInfo_AskToContinue(). This routine displays a movable modal dialog
- asking the user to press return to continue the test or click cancel to
- stop it. That way the user gets a chance to examine the test output
- before moving on to the next test. Additionally, if the comparison window
- was open when the composite test began, the test output will be compared
- after each test. While the continue dialog is up, the user can access the
- comparison menu to switch between the various channels. They can also
- move the comparison window by command-dragging its title bar.
-
- Note that calling a test from inside a composite test does not always
- produce identical behavior to running that same test by clicking the Run
- button in the settings window. For example, when you click Run, Sneak3view
- creates a new draw context, loads the selected texture and bitmap, if
- necessary, and adds them to each engine. When the test has completed it
- destroys the draw contexts, textures and bitmaps.
-
- On the other hand, calling S3TestInfo_RunTest() does not recreate
- everything in S3tTestInfo. The test you call will use the same draw
- context as the previous one. Sometimes this is exactly what you want in
- order to test the behavior of your draw context over time. In the case of
- the Game Test, this is not a problem since it loads everything it needs and
- then disposes of it all when it's finished. Be aware, however, that a test
- you call might actually change the state of the S3tTestInfo. It could,
- for example, delete the textures that were created at the beginning of the
- test. If the next test that is run depends on those textures, you'll
- encounter problems.
-
- If you do actually want the next test to receive fresh copies of everything
- in S3tTestInfo, call S3TestInfo_Refresh(). This will delete any existing
- draw contexts, textures, etc. and recreate them based on the current
- values of the S3tTestInfo's fields. Once again, the state that exists when
- a test is run may not be identical to the state of the settings window.
- Sometimes, of course, this is what you want. For instance, you could call
- S3OneTexturedRectangle() several times. In between each repetition, you
- could change the texture FSSpec to point to a different texture and then call
- S3TestInfo_Refresh(). This will provide a different texture to each call
- of S3OneTexturedRectangle().
-
-
- Registering a Test
- =========== = ====
-
- Once you have written your test code, you must register it so that it will
- show up in Sneak3view's Test menu. S3TestRegister.c contains a routine
- called S3Test_Init that gets called when the application starts up. In
- this function you must call S3Test_Register to register your test.
-
- S3Test_Register takes three parameters. The first is a C string containing
- the name of your test as you want it to appear in the menu. The second
- parameter is one or more of the values in the S3tTestPrereqs enumeration.
- If your test expects the user to select a texture before it is run, you
- must pass kS3Prereq_Texture. If you do not, the texture will never be
- created. kS3Prereq_Bitmap serves a similiar purpose for bitmaps. If your
- test needs both a texture and a bitmap, pass the sum of these two constants
- in this parameter. If neither a texture nor a bitmap is required, pass
- kS3Prereq_None.
-
- The third parameter is a pointer to your test routine. If you pass nil
- instead, a divider will be added to the Test menu at that point. The tests
- appear in the menu in the same order in which you register them.
-
- Rather than registering every test one by one in S3TestRegister.c, it is
- convenient to have one function per source file that in turn registers
- every test in that file. For instance, S3RandomTests_Register() registers
- all the tests in S3RandomTests.c. This lets you add tests to a particular
- file without editing S3TestRegister.c. Note that you will have to
- externally declare any functions you call in S3TestRegister at the top of
- that file.
-
- If there is something you need to do when the application is quitting, you
- can put it in S3Test_Exit.
-
-